package cn.edu.dlmu.cogo.register;

import cn.edu.dlmu.cogo.framework.annotation.Priority;
import cn.edu.dlmu.cogo.framework.config.JavaConfig;
import cn.edu.dlmu.cogo.framework.config.WebConfig;
import cn.edu.dlmu.cogo.framework.context.ApplicationContext;
import cn.edu.dlmu.cogo.framework.context.ApplicationContextAware;
import cn.edu.dlmu.cogo.framework.context.Environment;
import cn.edu.dlmu.cogo.framework.context.Level;
import cn.edu.dlmu.cogo.framework.utils.CogoClassUtil;
import cn.hutool.core.date.TimeInterval;
import cn.hutool.core.lang.Console;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;

import java.util.HashMap;
import java.util.Map;

/**
 * @author hongda.li@hand-china.com 2022/3/10 22:17
 */
@Priority(Level.Middle)
public class RegisterClientAware implements ApplicationContextAware {

    /**
     * 定时器，用以实现自动续租
     */
    private final TimeInterval interval = new TimeInterval();

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {

        // 判断是否开启了注册中心客户端
        boolean enableRegisterClient = CogoClassUtil.mainClassWithAnnotation(EnableRegisterClient.class);
        if (!enableRegisterClient) {
            return;
        }

        applicationContext.removeBean(CogoRegisterController.class);
        applicationContext.removeBean(CogoRegisterCenter.class);
        applicationContext.removeBean(LocalServiceCachePool.class);

        // 获取注册中心配置类，如果在容器中存在配置类则优先获取
        JavaConfig.setConfig(new RegisterConfig());
        WebConfig webConfig = new WebConfig();
        RegisterConfig registerConfig = JavaConfig.getConfig(RegisterConfig.class);
        webConfig.setPort(registerConfig.getPort());
        applicationContext.removeBean(WebConfig.class);
        applicationContext.setBean(webConfig);

        // 客户端自动注册
        try {
            if (!autoRegister(registerConfig)) {
                return;
            }
            autoRenew(registerConfig);
        } catch (Exception e) {
            Console.error("{} [CogoRegisterClient]与CogoRegister注册中心建立连接异常", Environment.getSystemTime());
        }
    }

    public boolean autoRegister(RegisterConfig config){
        if (config.isSelfRegister()) {
            Map<String, Object> param = new HashMap<>(8);
            param.put("serviceName",config.getServiceName());
            param.put("serviceHost",config.getHostname());
            param.put("serviceIp",config.getIp());
            param.put("servicePort",config.getPort());
            param.put("startTime", config.getStartTime());
            String postUrl = StrUtil.addSuffixIfNot(config.getRegisterServerUrl(),"/") + "register-center/register";
            String result = HttpUtil.post(postUrl, param);
            Console.log("{} [POST][{}]",Environment.getSystemTime(),postUrl);
            if (RegisterConstant.REGISTER_SUCCESS.equals(result)){
                Console.log("{} [CogoRegisterClient]注册中心客户端 : 服务注册成功[{}]",Environment.getSystemTime(),config.getServiceName());
                return true;
            }else {
                Console.error("{} [CogoRegisterClient]注册中心客户端 : 服务注册失败",Environment.getSystemTime());
                Console.error("{} [CogoRegisterClient]注册中心客户端 : 服务注册失败信息[{}]",Environment.getSystemTime(),result);
                return false;
            }
        }
        return false;
    }

    public void autoRenew(RegisterConfig config){
        ThreadUtil.execute(() -> {
            interval.start();
            while (true) {
                if (interval.intervalSecond() == config.getTimeToLive()) {
                    String getUrl = StrUtil.addSuffixIfNot(config.getRegisterServerUrl(),"/") + "register-center/renew?serviceName=" + config.getServiceName();
                    Console.log("{} [GET][{}]",Environment.getSystemTime(), getUrl);
                    String result = HttpUtil.get(getUrl);
                    if (RegisterConstant.RENEW_SUCCESS.equals(result)){
                        interval.restart();
                        Console.log("{} [CogoRegisterClient]注册中心客户端 : 服务续约成功[{}]",Environment.getSystemTime(),config.getServiceName());
                    }else {
                        Console.error("{} [CogoRegisterClient]注册中心客户端 : 服务续约失败",Environment.getSystemTime());
                        Console.error("{} [CogoRegisterClient]注册中心客户端 : 服务续约失败信息[{}]",Environment.getSystemTime(),result);
                        return;
                    }
                }
            }
        });
    }
}
